# -*- coding:utf-8 -*-
# @Time : 2020/7/14 00:18
# @Author: xingmeng
# @File : implement.py
import base64
import hashlib
import hmac
import re
import time
import urllib
import json
import grequests
import pymongo
import requests
import logging
from gevent import monkey

monkey.patch_all()
requests.packages.urllib3.disable_warnings()
logging.getLogger("requests").setLevel(logging.WARNING)

myclient = pymongo.MongoClient("mongodb://111.111.2.2")
mydb = myclient["monitor"]


def runInformation():
	"""
	通过project_id返回对应钉钉key及token
	"""
	mycol = mydb["task"]
	for i in mycol.find({"project_id": p_id}):
		ding_token = i['ding_token']
		ding_key = i['ding_key']
		is_ding = i['is_ding']
		return [ding_key, ding_token, is_ding]


def ding(tz):
	"""
	传入发送信息"tz"后，使用runInformation返回的参数可发送通知
	"""
	print(tz)
	# 获取加密timestamp、sign
	is_ding = runInformation()[2]
	if is_ding == 0:
		timestamp = str(round(time.time() * 1000))
		secret = runInformation()[1]
		secret_enc = secret.encode('utf-8')
		string_to_sign = '{}\n{}'.format(timestamp, secret)
		string_to_sign_enc = string_to_sign.encode('utf-8')
		hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
		sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
		# 进行请求
		url = runInformation()[0] + "&timestamp=" + timestamp + "&sign=" + sign
		HEADERS = {"Content-Type": "application/json ;charset=utf-8 "}
		data = {
			"msgtype": "text",
			"text": {
				"content": tz
			},
			"at": {
				"atMobiles": [],
				"isAtAll": "false"
			}
		}
		sendData = json.dumps(data)
		requests.DEFAULT_RETRIES = 5  # 增加重试连接次数
		s = requests.session()
		s.keep_alive = False
		requests.post(url, data=sendData, headers=HEADERS)
	else:
		pass


def ii(res_list, ca, interface_id, url, error_num, yapiurl, is_ding):
	"""
	拼接钉钉发送的内容，走此接口则使对应接口错误"error_num"增加1
	"""
	tz = "接口id：%s \n" \
		 "接口名称：%s \n" \
		 "接口地址：%s \n" \
		 "错误次数: %s \n" \
		 "状态码：%s \n" \
		 "备注：%s \n" % (interface_id, ca, url, error_num, res_list, yapiurl)
	if is_ding == 0:
		ding(tz)


def judgeResult(res_list, ca, interface_id, url, pid, response_time, error_num, yapiurl, is_ding, case_id):
	"""
	判断请求接口的返回，及记录错误、正确执行结果
	"""
	try:
		result = re.compile(r'\d+').findall(str(res_list))
		dict = {"res_list": result[0], "ca": ca, "interface_id": interface_id, "url": url, "pid": pid,
				"time": int(time.time()),
				"response_time": response_time}
		if re.match("^(3|4|5)", str(result[0])):
			err_log = mydb["err_log"]
			err_log.insert_one(dict)
		else:
			correct_log = mydb["correct_log"]
			correct_log.insert_one(dict)
		if res_list[0].status_code == 200:
			pass
		else:
			upErrorNum(case_id)
			ii(res_list[0].status_code, ca, interface_id, url, error_num + 1, yapiurl, is_ding)
	except Exception as e:
		upErrorNum(case_id)
		err_log = mydb["err_log"]
		err_log.insert_one(
			{"res_list": 404, "ca": ca, "interface_id": interface_id, "url": url, "pid": pid, "time": int(time.time()),
			 "error_num": error_num + 1, "yapiurl": yapiurl})
		ii(e, ca, interface_id, url, error_num + 1, yapiurl, is_ding)


def implementRequest(id):
	"""
	错误请求主体，传入项目id后，会现查找"error_num大于1"的所有接口
	大于1，则说明此接口有过错误
	执行后会调用judgeResult方法去判断此次执行结果
	"""
	global p_id
	p_id = id
	mycol = mydb["test"]
	try:
		for information in mycol.find({"project_id": int(id), "error_num": 0}):
			print(information)
			pid = information['project_id']
			interface_id = information['interface_id']
			ca = information['case_name']
			case_id = information['case_id']
			is_ding = information['is_ding']
			url = information['request_path']
			method = information['request_method']
			request_query = information['request_query']
			header = information['request_headers']
			error_num = information['error_num']
			yapiurl = 'http://111.111.1.1:3000/project/' + str(information['project_id']) + '/interface/api/' + str(
				information['interface_id'])
			if method == 'POST':
				start = time.time()
				req_list = [grequests.post(url,data=request_query, headers=header, timeout=23, verify=False)]
				res_list = grequests.map(req_list)
				response_time = time.time() - start
				judgeResult(res_list, ca, interface_id, url, pid, response_time, error_num, yapiurl, is_ding, case_id)
			else:
				start = time.time()
				req_list = [grequests.get(url, timeout=23, verify=False)]
				res_list = grequests.map(req_list)
				response_time = time.time() - start
				judgeResult(res_list, ca, interface_id, url, pid, response_time, error_num, yapiurl, is_ding, case_id)
	except:
		pass


def upErrorNum(case_id):
	"""
	传入case_id则会增加一次错误次数
	"""
	mycol = mydb["test"]
	myquery = ({"case_id": case_id})
	for information in (mycol.find({"case_id": case_id}, {"error_num": 1})):
		error_num = information['error_num']
		a = error_num + 1
		newvalues = {"$set": {"error_num": a}}
		mycol.update_one(myquery, newvalues)


if __name__ == '__main__':
	implementRequest(144)
